/**
 *  TextMash - simple IDE for Clojure
 *  
 *  Copyright (C) 2010 Aleksander Naszko
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package pl.olek.textmash.menu;

import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Map;

import javax.swing.Action;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.text.DefaultEditorKit;

import pl.olek.clojure.RemoteManager;
import pl.olek.textmash.TextMash;
import pl.olek.textmash.event.Event;
import pl.olek.textmash.event.EventDispatcher;
import pl.olek.textmash.event.EventListener;
import pl.olek.textmash.workspace.DialogBox;
import pl.olek.textmash.workspace.FindDialog;
import pl.olek.textmash.workspace.Settings;
import pl.olek.textmash.workspace.Workspace;

/**
 * 
 * @author anaszko
 *
 */
public class WorkspaceMenu extends JMenuBar {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8565568420546131868L;
	JMenu file, edit, text, transform, window, help, view, clojure;
	JMenu recentFiles, recentFolders, useEncoding, highlightSyntax;
	JMenu remoteClojures;
	JMenuItem clearRecentFiles, quickLookup, clearRecentFolders, wrapLines, copyFullPath;
	JMenuItem selectedEncoding, showLines, matchBrackets, verticalSelection;
	JMenuItem unixEnding, winEnding, macEnding;
	JMenu comments;
	Action defaultOpen;
	int recentOffset;

	/*
	 * final static String[] availableEncoding = { "ASCII", "UTF-8", "UTF-16",
	 * "ISO-8859-1", "ISO-8859-2", "Cp1252", "Cp1250" };
	 */

	final static String[] availableComments = { "//", "#", ";", "!", "--",
			"REM", "'", "*", "\\", "%" };

	public WorkspaceMenu(Workspace workspace) {
		fileMenu(workspace);
		editMenu(workspace);
		textMenu(workspace);
		viewMenu(workspace);
		clojureMenu(workspace);
		windowMenu(workspace);
		helpMenu(workspace);
		synchronizeClojure(workspace, false);
		EventDispatcher.getInstance().register(new EventListener() {

			@Override
			public void action(Event event) {
				synchronizedWorkspaces(false);

			}
		}, EventDispatcher.WORKSPACE_IS_DIRTY, EventDispatcher.WORKSPACE_SAVED);
	}

	public void synchronizeRecent(ArrayList<String> items, JMenu recent,
			ActionListener listener) {
		while (recent.getItemCount() > 1) {
			recent.remove(0);
		}
		if (!items.isEmpty()) {
			recent.getItem(0).setEnabled(true);
			recent.insertSeparator(0);
			for (String folder : items) {
				JMenuItem it = MenuBuilder.item(MenuBuilder.truncate(folder),
						-1, false, listener);
				it.putClientProperty("file", folder);
				recent.insert(it, 0);
			}
		} else {
			recent.getItem(0).setEnabled(false);
		}
	}

	public void synchronizeRecentFolders(final Workspace workspace) {
		synchronizeRecent(TextMash.getRecentFolders(), recentFolders,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {

						String selectedFile = selectFile(((JMenuItem) e
								.getSource()).getClientProperty("file")
								.toString());
						if (selectedFile != null) {

							workspace.actionOpenFile(selectedFile);

						}

					}
				});
	}

	public void synchronizedWorkspaces(boolean modify) {
		JMenu recentMenu = window;
		int offset = recentOffset;
		if (modify) {
			// System.out.println("Updating");
			while (recentMenu.getItemCount() > offset) {
				recentMenu.remove(offset);
			}
			int a = 0;
			for (final Workspace w : TextMash.getWorkspaces()) {
				// File f = new File(w.getW)
				int state = (w.isActive() || TextMash.getWorkspaces().size() == 1) ? MenuBuilder.SELECTED
						: MenuBuilder.UNSELECTED;
				final JMenuItem i = MenuBuilder.item(
						w.getShortWorkspaceTitle(), state, false, null);
				i.addActionListener(new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						w.toFront();
						i.setSelected(true);

					}
				});
				i.putClientProperty("ws", w);
				i.setEnabled(true);
				i.setSelected(state == MenuBuilder.SELECTED);
				recentMenu.insert(i, offset + a++);
			}
		} else {
			int to = recentMenu.getItemCount() - offset;
			while (--to >= 0) {
				JMenuItem i = recentMenu.getItem(offset + to);
				Workspace w = (Workspace) i.getClientProperty("ws");
				i.setSelected(w.isActive());
				i.setText(w.getShortWorkspaceTitle());
			}
		}
	}
	
	public void synchronizeClojure(final Workspace workspace, boolean connect) {
		ActionListener itemAction = new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				int c = remoteClojures.getItemCount();
				for(int i = 0; i < c; ++i) {
					remoteClojures.getItem(i).setSelected(false);
				}
				JMenuItem it = ((JMenuItem)e.getSource());
				it.setSelected(true);
				workspace.getTextPane().setTerminal(
					it.getClientProperty("remote").toString());
			}
		};
		remoteClojures.removeAll();
		for(Map.Entry<String, String> v :
			RemoteManager.getInstance().list().entrySet()) {
//			System.out.println("Listed");
			 JMenuItem item = MenuBuilder.item(v.getValue(),
					 v.getKey().equals(workspace.getTextPane().getTerminal()) ?
							 MenuBuilder.SELECTED :	 
					MenuBuilder.UNSELECTED, false, itemAction);
			item.putClientProperty("remote", v.getKey());
			item.addActionListener(itemAction);
			remoteClojures.add(item);
			
		}
		int n = remoteClojures.getItemCount();
		remoteClojures.setEnabled((n != 0));
		if (n == 1 && connect) {
			JMenuItem it = remoteClojures.getItem(0);
			it.setSelected(true);
			workspace.getTextPane().setTerminal( 
				it.getClientProperty("remote").toString());
		}
	}

	public void synchronizeRecentFiles(final Workspace workspace) {
		synchronizeRecent(TextMash.getRecentFiles(), recentFiles,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionOpenFile(((JMenuItem) e.getSource())
								.getClientProperty("file").toString());

					}
				});

	}

	public void synchronize(Settings cfg, Workspace workspace) {

		wrapLines.setSelected(cfg.isOn(Settings.WRAP_LINES));

		verticalSelection.setSelected(cfg.isOn(Settings.VERTICAL_SELECTION));

		matchBrackets.setSelected(cfg.isOn(Settings.MATCH_BRACKETS));

		showLines.setSelected(cfg.isOn(Settings.LINE_NUMBERS));

		defaultOpen.setEnabled((workspace.getDataSource().length() > 0));

		String ending;

		if (cfg.has(Settings.LINE_ENDING)) {
			ending = cfg.get(Settings.LINE_ENDING);
		} else {
			ending = (String) workspace.getTextPane().getDocument()
					.getProperty(DefaultEditorKit.EndOfLineStringProperty);

			if (ending == null || ending.length() == 0) {
				ending = System.getProperty("line.separator");
				cfg.set(Settings.LINE_ENDING, ending);
			}
		}

		macEnding.setSelected(ending.equals(macEnding
				.getClientProperty("ending")));
		winEnding.setSelected(ending.equals(winEnding
				.getClientProperty("ending")));
		unixEnding.setSelected(ending.equals(unixEnding
				.getClientProperty("ending")));

		quickLookup.setSelected(cfg.isOn(Settings.QUICK_LOOKUP));
		
		copyFullPath.setEnabled(!workspace.isUnnamed());

		String encoding = cfg.get(Settings.ENCODING);
		for (int i = useEncoding.getItemCount() - 1; i >= 0; --i) {
			JMenuItem e = useEncoding.getItem(i);
			if (e == null) {
				continue;
			}
			Object obj = e.getClientProperty("en");
			if (obj != null && obj.equals(encoding)) {
				selectedEncoding = e;
				e.setSelected(true);
			} else {
				e.setSelected(false);
			}
		}

		// if (!cfg.has(Settings.COMMENT)) {
		// cfg.set(Settings.COMMENT, "//");
		// }

		String cmt = cfg.get(Settings.COMMENT);
		for (int i = 2; i < comments.getItemCount(); ++i) {
			JMenuItem it = comments.getItem(i);
			boolean state = it.getClientProperty("comment").equals(cmt);
			it.setSelected(state);
		}

		synchronizeRecentFolders(workspace);
		synchronizeRecentFiles(workspace);
	}

	public String selectFile(String defaultFolder) {
		FileDialog fileDialog = new FileDialog((Frame) null, "Open File");
		if (defaultFolder != null) {
			fileDialog.setDirectory(defaultFolder);
		}
		fileDialog.setVisible(true);
		if (fileDialog.getFile() != null) {
			return new File(fileDialog.getDirectory(), fileDialog.getFile())
					.getAbsolutePath();
		}
		return null;
	}
	
	public void clojureMenu(final Workspace workspace) {
		add(clojure = new JMenu("Clojure"));
		clojure.add(workspace.getAction("spawnTerminal"));
		
		remoteClojures = new JMenu("Attach To");
		remoteClojures.setEnabled(false);
		clojure.add(remoteClojures);
		
		EventDispatcher.getInstance().register(null, 
				new EventListener() {
					
					@Override
					public void action(Event event) {
						
						synchronizeClojure(workspace, true);
						
						
					
					}
				}, EventDispatcher.REMOTE_CHANGED);
		clojure.add(workspace.getAction("configureClojure"));
		clojure.addSeparator();
		clojure.add(workspace.getAction("executeStatement"));
		clojure.add(workspace.getAction("executeFile"));
		
		
	}

	public void fileMenu(final Workspace workspace) {

		add(file = new JMenu("File"));

		file.add(MenuBuilder.item("New", KeyEvent.VK_N, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionNew();

					}
				}));
		file.add(MenuBuilder.item("Open...", KeyEvent.VK_O, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						String selectedFile = selectFile(null);
						if (selectedFile != null) {
							workspace.actionOpenFile(selectedFile);
						}
					}
				}));

		file.add(recentFiles = MenuBuilder.menu("Open Recent File",
				MenuBuilder.NO_KEY, false, null));
		recentFiles.add(clearRecentFiles = MenuBuilder.item("Clear Menu",
				MenuBuilder.NO_KEY, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						TextMash.actionClearRecentFiles();
					}
				}));

		clearRecentFiles.setEnabled(false);

		file.add(recentFolders = MenuBuilder.menu("Open Using Folder",
				MenuBuilder.NO_KEY, false, null));
		recentFolders.add(clearRecentFolders = MenuBuilder.item("Clear Menu",
				MenuBuilder.NO_KEY, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						TextMash.actionClearRecentFolders();
					}
				}));
		clearRecentFolders.setEnabled(false);

		file.addSeparator();
		file.add(MenuBuilder.item("Close", KeyEvent.VK_W, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionClose();

					}
				}));

		file.add(MenuBuilder.item("Save", KeyEvent.VK_S, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionSave();

					}
				}));
		file.add(MenuBuilder.item("Save As...", KeyEvent.VK_S, true,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionSaveAs();

					}
				}));
		file.add(MenuBuilder.item("Save All", MenuBuilder.NO_KEY, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						TextMash.actionSaveAll();

					}
				}));
		file.addSeparator();
		file.add(copyFullPath = MenuBuilder.item("Copy Full Path", MenuBuilder.NO_KEY, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {

						StringSelection stringSelection = new StringSelection(
								workspace.getDataSource());
						Clipboard clipboard = Toolkit.getDefaultToolkit()
								.getSystemClipboard();
						clipboard.setContents(stringSelection, null);
					}
				}));
		file.add(defaultOpen = workspace.getAction("defaultOpen"));
		
		

	}

	public void viewMenu(final Workspace workspace) {
		add(view = new JMenu("View"));

		//

		// text.add(view = new JMenu("View"));
		view.add(quickLookup = MenuBuilder.item("Mark Occurrences",
				MenuBuilder.SELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {

						workspace.setQuickLookup(((JMenuItem) e.getSource())
								.isSelected());

					}
				}));

		view.add(matchBrackets = MenuBuilder.item("Match Brackets",
				MenuBuilder.SELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionToggleMatchBrackets();

					}
				}));
		view.add(highlightSyntax = MenuBuilder.menu("Highlight Syntax",
				MenuBuilder.NO_KEY, false, null));
		
		highlightSyntax.add(MenuBuilder.item("Disable",
				MenuBuilder.SELECTED, false, null));
		highlightSyntax.add(MenuBuilder.item("Java",
				MenuBuilder.UNSELECTED, false, null));
		highlightSyntax.add(MenuBuilder.item("C#",
				MenuBuilder.UNSELECTED, false, null));		
		highlightSyntax.add(MenuBuilder.item("C/C++",
				MenuBuilder.UNSELECTED, false, null));
		highlightSyntax.add(MenuBuilder.item("Clojure",
				MenuBuilder.UNSELECTED, false, null));
		highlightSyntax.add(MenuBuilder.item("PHP",
				MenuBuilder.UNSELECTED, false, null));		
		highlightSyntax.add(MenuBuilder.item("Javascript",
				MenuBuilder.UNSELECTED, false, null));	
		highlightSyntax.add(MenuBuilder.item("HTML",
				MenuBuilder.UNSELECTED, false, null));			
		
		
		view.addSeparator();
		view.add(showLines = MenuBuilder.item("Show Line Numbers",
				MenuBuilder.SELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionToggleShowLineNumbers();

					}
				}));

		view.add(wrapLines = MenuBuilder.item("Wrap Lines",
				MenuBuilder.SELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionToggleWrapLines();

					}
				}));
		view.add(MenuBuilder.item("Show Selection Status",
				MenuBuilder.UNSELECTED, false, null));
	}

	public void editMenu(final Workspace workspace) {
		add(edit = new JMenu("Edit"));

		/*
		 * edit.add(MenuBuilder.item("Undo", KeyEvent.VK_Z, false, null));
		 * edit.add(MenuBuilder.item("Redo", KeyEvent.VK_Z, true, null));
		 */

		edit.add(workspace.getAction("undo"));

		edit.add(workspace.getAction("redo"));

		edit.addSeparator();
		edit.add(workspace.getAction("cut"));
		edit.add(workspace.getAction("copy"));
		edit.add(workspace.getAction("paste"));
		
		JMenu deleteMenu = MenuBuilder.menu("Delete", 
				MenuBuilder.NO_KEY, false, null);
		
		deleteMenu.add(workspace.getAction("delete"));
		deleteMenu.add(workspace.getAction("deleteLine"));

		deleteMenu.add(workspace.getAction("deleteRest"));
		deleteMenu.add(workspace.getAction("deleteEmptyLines"));
		edit.add(deleteMenu);
		edit.addSeparator();
		edit.add(workspace.getAction("selectAll"));
		edit.add(workspace.getAction("selectLine"));
		edit.add(verticalSelection = MenuBuilder.item("Select Vertically",
				MenuBuilder.UNSELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionToggleVerticalSelection();

					}
				}));
		/*
		 * edit.add(MenuBuilder.item("Select Greedy", MenuBuilder.UNSELECTED,
		 * false, null));
		 */
		edit.addSeparator();

		edit.add(MenuBuilder.item("Find...", KeyEvent.VK_F, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						new FindDialog(workspace);

					}
				}));
		edit.add(MenuBuilder.item("Find Next", KeyEvent.VK_G, false, null));
		edit.add(MenuBuilder.item("Find Previous", KeyEvent.VK_G, true, null));
		// edit.add(MenuBuilder.item("Replace...", KeyEvent.VK_R, false, null));
		// edit.addSeparator();

	}

	public void windowMenu(final Workspace workspace) {
		add(window = new JMenu("Window"));
		window.add(MenuBuilder.item("Close All", KeyEvent.VK_W, true,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						TextMash.actionCloseAll(workspace);

					}
				}));
		window.add(MenuBuilder.item("Close Others", MenuBuilder.NO_KEY, false,
				new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						TextMash.actionCloseOthers(workspace);
					}
				}));
		window.addSeparator();

		window.add(MenuBuilder.item("Bring All to Front", MenuBuilder.NO_KEY,
				false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						TextMash.actionBringToFront(workspace);
					}
				}));

		window.addSeparator();

		recentOffset = window.getItemCount();
	}

	public void commentMenu(final Workspace workspace) {
		add(comments = new JMenu("Comment"));

		comments.add(workspace.getAction("toggleComment"));
		comments.addSeparator();

		ActionListener listener = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

				String cmt = ((JMenuItem) e.getSource()).getClientProperty(
						"comment").toString();

				for (int i = 2; i < comments.getItemCount(); ++i) {
					JMenuItem it = comments.getItem(i);
					boolean state = it.getClientProperty("comment").equals(cmt);
					it.setSelected(state);
				}

				workspace.actionUseCommentStyle(cmt);
			}
		};

		comments.add(MenuBuilder.item("Java, C#, C++, PHP (//)",
				MenuBuilder.SELECTED, true, listener));
		comments.add(MenuBuilder.item("Perl, Python, Ruby (#)",
				MenuBuilder.UNSELECTED, true, listener));
		comments.add(MenuBuilder.item("Lisp, Scheme, assemblers (;)",
				MenuBuilder.UNSELECTED, true, listener));
		comments.add(MenuBuilder.item("Fortran, Basic Plus (!)",
				MenuBuilder.UNSELECTED, true, listener));
		comments.add(MenuBuilder.item("SQL (--)", MenuBuilder.UNSELECTED, true,
				listener));
		comments.add(MenuBuilder.item("Basic (REM)", MenuBuilder.UNSELECTED,
				true, listener));
		comments.add(MenuBuilder.item("Visual Basic, VBscript (')",
				MenuBuilder.UNSELECTED, true, listener));
		comments.add(MenuBuilder.item("Cobol (*)", MenuBuilder.UNSELECTED,
				true, listener));
		comments.add(MenuBuilder.item("Forth (\\)", MenuBuilder.UNSELECTED,
				true, listener));
		comments.add(MenuBuilder.item("TeX, Prolog, MATLAB (%)",
				MenuBuilder.UNSELECTED, true, listener));

		for (int i = 2; i < comments.getItemCount(); ++i) {
			comments.getItem(i).putClientProperty("comment",
					availableComments[i - 2]);
		}

		text.add(comments);
	}

	public void textMenu(final Workspace workspace) {
		add(text = new JMenu("Text"));

		// text.addSeparator();

		JMenu dictionary = new JMenu("Dictionary");

		dictionary.add(workspace.getAction("suggestWord"));

		dictionary.addSeparator();

		dictionary.add(MenuBuilder.item("Build on Open", MenuBuilder.SELECTED,
				false, null));

		dictionary.add(MenuBuilder.item("Rebuild on Save",
				MenuBuilder.SELECTED, false, null));

		dictionary.add(MenuBuilder.item("Clear with Recent",
				MenuBuilder.SELECTED, false, null));

		text.add(dictionary);

		commentMenu(workspace);

		text.add(workspace.getAction("shiftRight"));
		text.add(workspace.getAction("shiftLeft"));
		text.addSeparator();

		text.add(workspace.getAction("capitalizeWords"));
		text.add(workspace.getAction("capitalizeSentences"));
		text.add(workspace.getAction("upperCase"));
		text.add(workspace.getAction("lowerCase"));

		// transformMenu(workspace);

		text.addSeparator();

		JMenu modifyEndLine = MenuBuilder.menu("Line Endings",
				MenuBuilder.NO_KEY, false, null);
		text.add(modifyEndLine);

		modifyEndLine.add(unixEnding = MenuBuilder.item("Unix (LF) ",
				MenuBuilder.SELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionSetLineEnding((String) unixEnding
								.getClientProperty("ending"));
						macEnding.setSelected(false);
						winEnding.setSelected(false);
					}
				}));
		unixEnding.putClientProperty("ending", "\n");
		modifyEndLine.add(macEnding = MenuBuilder.item("Macintosh (CR)",
				MenuBuilder.UNSELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionSetLineEnding((String) macEnding
								.getClientProperty("ending"));
						winEnding.setSelected(false);
						unixEnding.setSelected(false);
					}
				}));
		macEnding.putClientProperty("ending", "\r");
		modifyEndLine.add(winEnding = MenuBuilder.item("Windows (CR/LF)",
				MenuBuilder.UNSELECTED, false, new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						workspace.actionSetLineEnding((String) winEnding
								.getClientProperty("ending"));
						macEnding.setSelected(false);
						unixEnding.setSelected(false);
					}
				}));
		winEnding.putClientProperty("ending", "\r\n");
		encodingMenu(workspace);

	}

	public void transformMenu(final Workspace workspace) {
		text.add(transform = new JMenu("Transform"));

		JMenu numeralsConverter = MenuBuilder.menu("Numerals",
				MenuBuilder.NO_KEY, false, null);
		transform.add(numeralsConverter);

		numeralsConverter.add(MenuBuilder.item("Arabic to Roma",
				MenuBuilder.NO_KEY, false, null));
		numeralsConverter.add(MenuBuilder.item("Roma to Arabic",
				MenuBuilder.NO_KEY, false, null));
		transform.add(MenuBuilder.item("Convert CSV Export to SQL Insert",
				MenuBuilder.NO_KEY, false, null));
		transform.add(MenuBuilder.item("Format", KeyEvent.VK_F, true, null));

		transform.add(MenuBuilder.item("Form in Columns", MenuBuilder.NO_KEY,
				false, null));

		// challange.add(MenuBuilder.item("Open in default editor",
		// KeyEvent.VK_E,
		// false, null));

		transform.add(MenuBuilder.item("Correct Indentation",
				MenuBuilder.NO_KEY, false, null));
		transform.add(MenuBuilder.item("Expand", MenuBuilder.NO_KEY, false,
				null));
		transform.add(MenuBuilder.item("Randomize", MenuBuilder.NO_KEY, false,
				null));
		// challange.add(MenuBuilder.item("Run in Clojure REPL", KeyEvent.VK_E,
		// true, null));
	}

	public void encodingMenu(final Workspace workspace) {
		useEncoding = MenuBuilder.menu("Use Encoding", MenuBuilder.NO_KEY,
				false, null);

		ActionListener encodingAction = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

				JMenuItem choosed = (JMenuItem) e.getSource();

				String en = choosed.getClientProperty("en").toString();

				if (workspace.isUnnamed()) {
					workspace.actionUseEncoding(en, false);
				} else {
					switch (DialogBox.showDialogBox(workspace, "File Encoding",
							"Do you want to convert the file to the new encoding or\n"
									+ "reinterpret it using the new encoding?",
							0, 3, "Reinterpret", "", "Cancel", "Convert")) {
					case 0:
						workspace.actionUseEncoding(en, true);
						break;
					case 3:
						workspace.actionUseEncoding(en, false);
						break;
					case 2:
						choosed.setSelected(false);
						return;

					}
				}

				selectedEncoding.setSelected(false);
				selectedEncoding = choosed;
				selectedEncoding.setSelected(true);
			}
		};

		int ii = EncodingTable.length();
		JMenuItem seit;
		for (int i = 0; i < ii; ++i) {
			String[] en = EncodingTable.get(i);
			if (en == null) {
				useEncoding.addSeparator();
			} else if (en[1] == null) {
				continue;
			} else if (selectedEncoding == null) {
				useEncoding.add(selectedEncoding = MenuBuilder.item(en[0],
						MenuBuilder.SELECTED, false, encodingAction));
				selectedEncoding.putClientProperty("en", en[1]);
			} else {
				useEncoding.add(seit = MenuBuilder.item(en[0],
						MenuBuilder.UNSELECTED, false, encodingAction));
				seit.putClientProperty("en", en[1]);
			}
		}

		text.add(useEncoding);
	}

	public void helpMenu(final Workspace workspace) {
		add(help = new JMenu("Help"));
		help.add(MenuBuilder.item("Introduction...", MenuBuilder.NO_KEY, false,
				null));
		help.add(MenuBuilder.item("Cheat Sheet...", MenuBuilder.NO_KEY, false,
				null));
		help
				.add(MenuBuilder.item("Donate...", MenuBuilder.NO_KEY, false,
						null));
	}

}
